#include <cv.h>
#include <highgui.h>

#include <stdio.h>
#include <math.h>
#include "config.h"

/* README
 * Ce test utilise edge
 * ne pas utiliser edge dans la fonction finale : échec !
 * */
static const char* wndedge         = "edge";
static const char* wndgray         = "gray";
static const char* wndcedge        = "cedge";
static const char* wndimgedge      = "img edge";
static const char* wndimggray      = "img gray";
static const char* wndimggraycedge = "img graycedge";

static int edge_thresh = 30;
static IplImage* imgoriginale;
static IplImage* imgToDisplayEdge;
static IplImage* imgToDisplayGrayCEdge;
static IplImage* imgToDisplayGray;
static IplImage* edge;
static IplImage* cedge;
static IplImage* gray;
static IplImage* graycedge;
static CvMemStorage* storageedge;
static CvMemStorage* storagegray;
static CvMemStorage* storagegraycedge;
static CvSeq* circlesedge;
static CvSeq* circlesgray;
static CvSeq* circlesgraycedge;
static char tbarname[] = "Threshold";
static int tailleMax = 0;

// define a trackbar callback
void on_trackbar(int h)
{
	printf("<on_trackbar> : début de la fonction\n");
	cvCopy(imgoriginale, imgToDisplayEdge, NULL);
	cvCopy(imgoriginale, imgToDisplayGrayCEdge, NULL);
	cvCopy(imgoriginale, imgToDisplayGray, NULL);
    cvSmooth( gray, edge, CV_BLUR, 3, 3, 0, 0 );
    cvNot( gray, edge );

    // Run the edge detector on grayscale
    cvCanny(gray, edge, (float)edge_thresh, (float)edge_thresh*3, 3);
    cvZero( cedge );
    
    // copy edge points
    cvCopy( imgToDisplayEdge, cedge, edge );
    // get a gray copy of cedge
	cvCvtColor(cedge, graycedge, CV_BGR2GRAY);
	printf("<on_trackbar> : création des images OK\n");
	
	circlesedge      = cvHoughCircles( edge     , storageedge     , CV_HOUGH_GRADIENT, 2, 10, 200, 100, 10, tailleMax/4);
	printf("<on_trackbar> : création du cercle circlesedge OK\n");
	circlesgray      = cvHoughCircles( gray     , storagegray     , CV_HOUGH_GRADIENT, 2, 10, 200, 100, 10, tailleMax/4);
	printf("<on_trackbar> : création du cercle circlesgray OK\n");
	circlesgraycedge = cvHoughCircles( graycedge, storagegraycedge, CV_HOUGH_GRADIENT, 2, 10, 200, 100, 10, tailleMax/4);
	printf("<on_trackbar> : création du cercle circlesgraycedge OK\n");
	printf("<on_trackbar> : création des cercles OK\n");
	
	int i;
	for( i = 0; i < circlesedge->total; i++ )
	{
	     float* p = (float*)cvGetSeqElem( circlesedge, i );
	     cvCircle( imgToDisplayEdge, cvPoint(cvRound(p[0]),cvRound(p[1])), 3            , CV_RGB(0,255,0), -1, 8, 0 );
	     cvCircle( imgToDisplayEdge, cvPoint(cvRound(p[0]),cvRound(p[1])), cvRound(p[2]), CV_RGB(255,0,0),  3, 8, 0 );
	}
	for( i = 0; i < circlesgray->total; i++ )
	{
	     float* p = (float*)cvGetSeqElem( circlesgray, i );
	     cvCircle( imgToDisplayGray, cvPoint(cvRound(p[0]),cvRound(p[1])), 3            , CV_RGB(0,255,0), -1, 8, 0 );
	     cvCircle( imgToDisplayGray, cvPoint(cvRound(p[0]),cvRound(p[1])), cvRound(p[2]), CV_RGB(255,0,0),  3, 8, 0 );
	}
	for( i = 0; i < circlesgraycedge->total; i++ )
	{
	     float* p = (float*)cvGetSeqElem( circlesgraycedge, i );
	     cvCircle( imgToDisplayGrayCEdge, cvPoint(cvRound(p[0]),cvRound(p[1])), 3            , CV_RGB(0,255,0), -1, 8, 0 );
	     cvCircle( imgToDisplayGrayCEdge, cvPoint(cvRound(p[0]),cvRound(p[1])), cvRound(p[2]), CV_RGB(255,0,0),  3, 8, 0 );
	}
	printf("<on_trackbar> : dessin des cercles sur les images OK\n");
	
    cvShowImage( wndedge        , edge );
    cvShowImage( wndgray        , gray );
    cvShowImage( wndcedge       , cedge);
    cvShowImage( wndimgedge     , imgToDisplayEdge);
    cvShowImage( wndimggray     , imgToDisplayGray);
    cvShowImage( wndimggraycedge, imgToDisplayGrayCEdge);
}

int test2(int argc, char** argv)
{
	int numImage;
	printf("<test2> : debut de la fonction\n");
    cvNamedWindow( wndedge        , 2);
    cvNamedWindow( wndgray        , 2);
    cvNamedWindow( wndcedge       , 2);
    cvNamedWindow( wndimgedge     , 2);
    cvNamedWindow( wndimggray     , 2);
    cvNamedWindow( wndimggraycedge, 2);
    for( numImage = 0; names[numImage] != 0; numImage++ )
    {
    	char nomImage[40] = "";
    	strcat(nomImage, folder);
    	strcat(nomImage, names[numImage]);
        // load i-th image
        int touche;
        int width, height;
        
    	imgoriginale = cvLoadImage( nomImage, 1 );
        if( !imgoriginale )
        {
            printf("<mainHoughcircles> Couldn't load %s\n", nomImage );
            continue;
        }
		printf("<test2> : Image %s chargée\n", names[numImage]);
        width  = imgoriginale->width;
        height = imgoriginale->height;
        tailleMax = MAX(width,height);
		// Create the output image
		cedge = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, 3);
		
		// Convert to grayscale
	    edge         = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, 1);
	    gray         = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, 1);
	    graycedge    = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, 1);
		imgToDisplayEdge     = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, 3);
		imgToDisplayGrayCEdge= cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, 3);
		imgToDisplayGray     = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, 3);
	    storageedge      = cvCreateMemStorage(0);
	    storagegray      = cvCreateMemStorage(0);
	    storagegraycedge = cvCreateMemStorage(0);
	    
		cvCvtColor(imgoriginale, gray, CV_BGR2GRAY);
	
	    // create a toolbar 
	    cvCreateTrackbar(tbarname, wndedge, &edge_thresh, 100, on_trackbar);
	
	    // Show the image
	    on_trackbar(0);
	
	    // Wait for a key stroke; the same function arranges events processing
	    touche = cvWaitKey(0);
	    cvReleaseImage(&imgoriginale);
	    cvReleaseImage(&imgToDisplayEdge);
	    cvReleaseImage(&imgToDisplayGrayCEdge);
	    cvReleaseImage(&imgToDisplayGray);
	    cvReleaseImage(&gray);
	    cvReleaseImage(&edge);
	    cvReleaseImage(&cedge);
	    cvReleaseImage(&graycedge);
	    cvClearMemStorage( storageedge      );
	    cvClearMemStorage( storagegray      );
	    cvClearMemStorage( storagegraycedge );
        if( (char)touche == 27 )
            break;
    }
    cvDestroyWindow( wndedge        );
    cvDestroyWindow( wndgray        );
    cvDestroyWindow( wndcedge       );
    cvDestroyWindow( wndimgedge     );
    cvDestroyWindow( wndimggray     );
    cvDestroyWindow( wndimggraycedge);
    return 0;
}
